package grame;
import java.awt.Color;
/**
 * Entities are basically characters that can be used as players, aggressive or passive monsters/creatures.
 * @author moomoohk (moomoohk@ymail.com)
 */
public class Entity extends Thread
{
	private String type, name;
	private int level, range, points;
	private Color color;
	private Coordinates pos;
	private boolean player, rendered, chasing, strolling;
	private Entity target;
	private Base b;
	private long speed;
	/**
	 * Generates completely random entity
	 * @param b Base in which entity is to be rendered
	 */
	public Entity(Base b)
	{
		this(GameUtils.randomGen()[1], GameUtils.randomGen()[0], 1, GameUtils.randomColor(), b, false);
	}
	/**
	 * Generates non-playable entity
	 * @param type Type
	 * @param name Name
	 * @param level Starting level
	 * @param color Color
	 * @param b Base in which entity is to be rendered
	 */
	public Entity(String type, String name, int level, Color color, Base b)
	{
		this(type, name, level, color, b, false);
	}
	/**
	 * Generates an entity
	 * @param type Type
	 * @param name Name
	 * @param level Starting level
	 * @param color Color
	 * @param b Base in which entity is to be rendered
	 * @param player Sets whether entity is playable or not
	 */
	public Entity(String type, String name, int level, Color color, Base b, boolean player)
	{
		this.type=type;
		this.name=name;
		this.level=level;
		this.color=color;
		this.pos=new Coordinates();
		this.player=player;
		this.target=null;
		this.chasing=false;
		this.strolling=false;
		this.b=b;
		this.speed=500; //Chasing speed
		this.range=5;
		this.rendered=false;
		this.color=Color.green;
		this.points=0;
		try
		{
			Thread.sleep(50);
		}
		catch(Exception e)
		{
			System.out.println(e.getMessage());
		}
		if(!this.player)
			this.start();
	}
	public void wait(int mult)
	{
		try 
		{
			sleep(this.speed*mult);
		} 
		catch (InterruptedException e) 
		{
			e.printStackTrace();
		}
	}
	public void run()
	{
		while(!this.player)
		{
			if(this.rendered)
			{
				Coordinates c=this.pos;
				System.out.println(c.toString());
				System.out.println(this.pos.toString());
				int mult=1;
				wait(mult);
				if((this.chasing)&&(this.target!=null))
				{
					if(/*(this.pos.distance(target.getPos())>1)&&*/(this.pos.distance(target.getPos())<this.range*2)) //In range
					{
						this.color=Color.red;
						Coordinates target=this.target.pos;
						Dir d=new Dir(this.pos, target);
						c=new Coordinates(this.pos.addDir(d));
						if((d.toString().length()>6)&&(this.b.isOccupied(c)))
						{
							c=new Coordinates(this.pos);
							String word=d.toString();
							int space=word.indexOf(' ');
							Dir first=new Dir(word.substring(0, space));
							Dir second=new Dir(word.substring(space + 1, word.length() - 1));
							Dir newd=new Dir(0, 0);
							if(!b.isOccupied(c.addDir(first)))
								newd=first;
							if(!b.isOccupied(c.addDir(second)))
								newd=second;
							c=c.addDir(newd);
						}
					}
					else
						if(this.pos.distance(this.target.getPos())==1) //Caught target
							this.chasing=false;
						else
						{
							this.color=Color.orange;
							if(this.strolling) //Too far
							{
								Coordinates[] sur=this.pos.getSurrounding();
								int random=(int)(Math.random()*sur.length);
								while(!b.isInMap(sur[random]))
									random=(int)(Math.random()*sur.length);
								c=sur[random];
								mult=2;
							}
						}
				}
				else
					if(this.strolling)
					{
						this.color=Color.green;
						Coordinates[] sur=this.pos.getSurrounding();
						int random=(int)(Math.random()*sur.length);
						while(!b.isInMap(sur[random]))
							random=(int)(Math.random()*sur.length);
						c=sur[random];
						mult=2;
					}
				this.b.render(this, c);
			}
		}
	}
	public boolean reachedTarget()
	{
		if((this.target!=null)&&(this.pos.distance(this.target.getPos())==1))
			return true;
		return false;
	}
	public Coordinates getPos()
	{
		return this.pos;
	}
	void setPos(Coordinates c)
	{
		this.pos=c;
	}
	public Color getColor() 
	{
		return this.color;
	}
	public boolean isPlayer()
	{
		return this.player;
	}
	public void unPlayer()
	{
		this.player=false;
		this.start();
	}
	public void makePlayer()
	{
		if(!this.b.hasPlayer())
		{
			this.player=true;
			this.b.addPlayer();
		}
	}
	/**
	 * Sets the entities range (the distance in which it'll detect and follow targets)
	 * @param range The range to set (set 0 to make range unlimited)
	 */
	public void setRange(int range)
	{
		this.range=range;
		if(range==0)
		{
			Coordinates ul=new Coordinates(0, 0), ur=new Coordinates(b.getColumns()-1, 0), dl=new Coordinates(0, b.getRows()-1), dr=new Coordinates(b.getColumns()-1, b.getRows()-1);
			this.range=Math.max(ul.distance(dr), ur.distance(dl));
		}
	}
	public void setTarget(Entity ent)
	{
		this.target=ent;
	}
	public void  setChasing(boolean f)
	{
		this.chasing=f;
	}
	public void setStrolling(boolean f)
	{
		this.strolling=f;
	}
	/**public void strolling(boolean f)
	{
		this.strolling=f;
		if(f)
			stroll();
	}
	private void stroll()
	{
		while(this.strolling)
		{
			if(this.target!=null)
				sniff();
			this.b.delay(this.speed*2);
			Coordinates[] sur=this.pos.getSurrounding();
			int random=(int)(Math.random()*sur.length);
			while(!b.isInMap(sur[random]))
				random=(int)(Math.random()*sur.length);
			b.render(this, sur[random]);
		}
	}*/
	public void setSpeed(long speed)
	{
		this.speed=speed;
	}
	public long getSpeed()
	{
		return this.speed;
	}
	public String toString()
	{
		return this.name+": Level "+this.level+" "+this.type+" ("+this.pos.getX()+", "+this.pos.getY()+") "+this.player;
	}
	public void setRendered(boolean f) 
	{
		this.rendered=f;
	}
	public boolean isRendered() 
	{
		return this.rendered;
	}
	public void addPoints(int amount)
	{
		this.points+=amount;
		System.out.println(this.points);
	}
	public int getPoints()
	{
		return this.points;
	}
}

